package com.motu.monstercity.server.game.logichandler;

import com.google.protobuf.InvalidProtocolBufferException;
import com.motu.monstercity.module.common.network.RequestParam;
import com.motu.monstercity.protocol.Common;
import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.protocol.CsGameWorld;
import com.motu.monstercity.protocol.CsGameWorld.*;
import com.motu.monstercity.server.game.base.AllParam;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.LockKey;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.bag.BagConstant;
import com.motu.monstercity.server.game.commondata.bag.Item;
import com.motu.monstercity.server.game.commondata.bag.ItemId;
import com.motu.monstercity.server.game.commondata.build.BuildConstant;
import com.motu.monstercity.server.game.commondata.maintask.MainTaskConstant;
import com.motu.monstercity.server.game.commondata.rank.RankConstant;
import com.motu.monstercity.server.game.commondata.skill.SkillConstant;
import com.motu.monstercity.server.game.commondata.world.WorldConstant;
import com.motu.monstercity.server.game.commondata.world.WorldEvent;
import com.motu.monstercity.server.game.commondata.world.WorldRadar;
import com.motu.monstercity.server.game.commondata.worldboss.WorldBoss;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.log.ThinkingDataManager;
import com.motu.monstercity.server.game.logic.*;
import com.motu.monstercity.server.game.timedtask.TimeTaskCmd;
import com.motu.monstercity.server.game.timedtask.TimedTaskManager;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.toolset.ErrorWord;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.shareddata.Lock;

import java.util.ArrayList;
import java.util.List;

public class WorldHandler {
    // CMD_GAME_WORLD_MAIN_INFO = 73501; // 大世界行军模块的用户数据 [2]每次打开请求，各种事件会根据时间进行刷新结算
    public static Object CMD_GAME_WORLD_MAIN_INFO(RequestParam clientParam) throws Exception {
        CSGameWorldMainInfoRequest request = CSGameWorldMainInfoRequest.parseFrom(clientParam.getData());
        CSGameWorldMainInfoResponse.Builder response = CSGameWorldMainInfoResponse.newBuilder();
        long userId = clientParam.getUserId();

        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldManager.checkWorldMoudleOpen(userInfo)) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }

        UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
        UserBuild userBuild = BuildManager.getUserBuild(userId, BuildConstant.BUILD_ID_RADAR);
        WorldRadar worldRadar = WorldManager.getWorldRadar(userBuild.getLevel());
        if (worldRadar == null) {
            return ErrorWord.NOT_DATA;
        }

        PBUserData.Builder pbUserData = response.getUserBuilder();
        // 解锁事件坑位，刷新行军队伍信息，刷新事件放到事件队列里，从事件队列里取事件更新到事件坑位
        WorldManager.unlockEventLocation(userId, userWorldInfo, worldRadar);// 解锁事件坑位
        WorldManager.refreshWorldTeam(pbUserData, userInfo, userWorldInfo);// 刷新结算行军队列，未到达则不做更新，已达到，则更新队伍，清除事件坑位里的数据，如果已返回基地，则生成战报，更新干员信息，伤兵信息
        if (WorldManager.checkIsNeedRefreshEvent(userWorldInfo.getEventRefreshTime())) {// 距离上次刷新过了0点8点16点
            WorldManager.refreshEvent(userId, userWorldInfo, worldRadar);// 刷新事件，放到事件队列里面
        }
        List<UserWorldEventLocation> locationList = WorldManager.getUserWorldEventLocationList(userInfo.getId());
        WorldManager.updateAllEventLocation(userInfo, userWorldInfo, worldRadar, locationList, false);// 从事件队列里取事件更新到事件坑位

        // 解锁悬赏事件
        WorldManager.unlockOfferEvent(userInfo);
        // 解锁世界boss事件
        WorldBossManager.unlockWorldBossEvent(userInfo);

        for (UserWorldEventLocation userWorldEventLocation : locationList) {
            // 事件已过期，普通事件，额外事件， 紧急触发的事件且无部队行军 重置数据
            if (userWorldEventLocation.isExpire(TimeUtils.getCurTime())) {
                if (userWorldEventLocation.isCommonType() || userWorldEventLocation.isExtraType() || (userWorldEventLocation.isUrgentType() && userWorldEventLocation.isNotTeamMarch())) {
                    userWorldEventLocation.cleanData();
                    userWorldEventLocation.update();
                }
            }
            ProtoDataUtils.updatePBUserData(pbUserData, userWorldEventLocation, true);

            List<UserWorldEventLocationTeam> userWorldEventLocationTeamList = WorldManager.getUserWorldEventLocationTeamList(userId, userWorldEventLocation.getLocationId());
            for (UserWorldEventLocationTeam userWorldEventLocationTeam : userWorldEventLocationTeamList) {
                ProtoDataUtils.updatePBUserData(pbUserData, userWorldEventLocationTeam, true);
            }
        }
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldInfo, true);


        return response;
    }

    // CMD_GAME_WORLD_EVENT_GOTO = 73502; // 派遣干员，携带兵力，去完成某坑位的事件，带兵出征
    public static Object CMD_GAME_WORLD_EVENT_GOTO(RequestParam clientParam) throws Exception {
        CSGameWorldEventGotoRequest request = CSGameWorldEventGotoRequest.parseFrom(clientParam.getData());
        CSGameWorldEventGotoResponse.Builder response = CSGameWorldEventGotoResponse.newBuilder();
        long userId = clientParam.getUserId();

        int locationId = request.getLocationId();
        int teamId = request.getTeamId();
        List<Integer> partnerIds = request.getPartnerList();
        int soldier = request.getSoldier();
        int coordX = request.getCoordX();
        int coordY = request.getCoordY();
        long curTime = TimeUtils.getCurTime();

        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldManager.checkWorldMoudleOpen(userInfo)) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }

        UserWorldEventLocation userWorldEventLocation = WorldManager.getUserWorldEventLocation(userId, locationId);
        if (userWorldEventLocation == null || userWorldEventLocation.getEventId() == 0 || userWorldEventLocation.isExpire(curTime)) {
            return ErrorWord.REPEATED_OPERATION;// 该坑位事件已经过期
        }

        // 如果是世界Boss的事件  不走事件表
        if(locationId == WorldConstant.WORLD_EVENT_LOCATION_ID_BOSS){
            ErrorWord invalidOperation = WorldBossManager.gotoWorldBoss(userInfo, userId, teamId, soldier, partnerIds, response, userWorldEventLocation, locationId, curTime, coordX, coordY);
            if (invalidOperation != null) return invalidOperation;
            return response;
        }

        WorldEvent worldEvent = WorldManager.getWorldEvent(userWorldEventLocation.getEventId());
        if (worldEvent == null) {
            return ErrorWord.NOT_DATA;// 未配置事件
        }

        UserWorldTeam userWorldTeam = WorldManager.getUserWorldTeam(userId, teamId);
        if (userWorldTeam == null || userWorldTeam.getStatus() != WorldConstant.WORLD_TEAM_STATUS_0) {
            return ErrorWord.WRONG_STATUS;// 该队伍不是空闲状态
        }
        if (userWorldTeam.isTmp() && curTime > userWorldTeam.getValidTime()) {
            return ErrorWord.WRONG_STATUS;// 临时行军队列已经过了有效期
        }

        UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
        if (userWorldInfo.getEnergy() < worldEvent.getEventEnergy()) {
            return ErrorWord.ITEM_LACK;//  体力不足
        }

        UserCityInfo userCityInfo = BuildManager.getUserCityInfo(userId);
        if (soldier < worldEvent.getTroopsLimit() || soldier > userCityInfo.getCurSoldier()) {
            return ErrorWord.ITEM_LACK;// 兵力不能低于下线， 兵力不足,
        }

        if (partnerIds.size() > WorldConstant.WORLD_TEAM_PARTNER_MAX || partnerIds.size() < 1) {
            return ErrorWord.ALREADY_MAX;// 一个队伍只能排1-3个干员出征
        }

        UserPower userPower = GameUser.getUserPower(userId);
        List<UserWorldPartner> partnerList = new ArrayList<>();
        List<UserPartner> userPartnerList = new ArrayList<>();
        JsonArray jsonArray = new JsonArray();
        int maxSoldier = 0;// 携带的兵力上限
        for (int i=0; i<partnerIds.size(); i++) {
            int partnerId = partnerIds.get(i);
            UserPartner userPartner = PartnerManager.getUserPartner(userId, partnerId);
            if (userPartner == null) {
                return ErrorWord.WRONG_STATUS;// 该干员未获得
            }
            UserWorldPartner userWorldPartner = WorldManager.getUserWorldPartner(userId, partnerId);
            if (userWorldPartner.getTeamId() > 0) {
                return ErrorWord.REPEATED_OPERATION;// 该干员已经在出征中了
            }
            partnerList.add(userWorldPartner);
            userPartnerList.add(userPartner);
            jsonArray.add(partnerId);

            maxSoldier += userPartner.takeSoldierMax();
        }

        if (soldier > maxSoldier) {
            return ErrorWord.ALREADY_MAX;// 携带的兵力超过了上限
        }

        long totalPower = 0L;// 总的战力
        int addValue = WorldManager.getWorldPowerAdd(worldEvent, soldier);// 携带兵力对战力的加成
        for (UserPartner userPartner : userPartnerList) {
            int skillAdd = WorldManager.countWorldPowerAdd(userPartnerList, SkillConstant.EFFECT_TYPE_104, userPartner.getCharacterType());// 百分比
            int addCv = WorldManager.countWorldPowerAdd(userPartnerList, SkillConstant.EFFECT_TYPE_103, userPartner.getCharacterType());// 固定值
            long partnerPower = GameUser.countPowerByPartner(userId, userPartner.getPartnerId(), userPartner, userPower, addValue + skillAdd) + addCv;// 某个干员的当前总战力, 基础战力 + 基础战力 * 加成（通用加成+模块加成） + 加的固定值
            totalPower += partnerPower;
        }

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();

        MainTaskManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_68, 1);// 完成{0}次事件 出征一次计一次就行
        MainTaskManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_67, worldEvent.getEventEnergy());// 消耗{0}远征体力
        MainTaskManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_251, worldEvent.getEventEnergy());// 累计消耗{0}远征体力

        userCityInfo.addSoldierBattle(soldier);// 增加战斗中的士兵，减少兵力
        userCityInfo.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userCityInfo);// 兵力信息

        WorldManager.createLoactionTeamInfo(pbUserData, userId, userWorldEventLocation, userWorldTeam);//  创建事件坑位的队伍派遣信息

        // 出征的时候有概率触发紧急事件，放在创建派遣信息后面，里面判断时需要用到
        WorldManager.creatUrgentEvent(pbUserData, userInfo, userWorldInfo);
        userWorldInfo.subEnergy(userInfo, worldEvent.getEventEnergy(), LogType.WORLD_TEAM_GO);
        userWorldInfo.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldInfo);// 扣除体力

        userWorldTeam.putStatus(WorldConstant.WORLD_TEAM_STATUS_1);
        userWorldTeam.putLocationId(locationId);
        userWorldTeam.putStartTime(curTime);
        userWorldTeam.putPartner(jsonArray.toString());
        userWorldTeam.putSoldier(soldier);
        userWorldTeam.putPower(totalPower);
        userWorldTeam.putTimeLeft(userWorldEventLocation.getOnewayTime());
        userWorldTeam.putUpdateTime(curTime);
        userWorldTeam.putEventId(userWorldEventLocation.getEventId());
        userWorldTeam.putForces(userWorldEventLocation.getForces());
        userWorldTeam.putOnewayTime(WorldManager.countWayTime(userPartnerList, userWorldEventLocation.getOnewayTime()));
        userWorldTeam.putCoordX(coordX);
        userWorldTeam.putCoordY(coordY);
        userWorldTeam.putUniqeId(Tool.getUUID());
        userWorldTeam.putTotalForces(userWorldEventLocation.getTotalForces());
        userWorldTeam.putRandomReward(userWorldEventLocation.getRandomReward());
        userWorldTeam.putBoxReward(userWorldEventLocation.getBoxReward());
        userWorldTeam.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldTeam);// 队伍信息

        for (UserWorldPartner userWorldPartner : partnerList) {
            userWorldPartner.putTeamId(teamId);
            userWorldPartner.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userWorldPartner, true);// 干员信息
        }

        int fightResult = userWorldTeam.countFightResult();
        response.setResult(fightResult);

        return response;
    }


    // CMD_GAME_WORLD_EVENT_ARRIVE = 73503; // 行军队列抵达坑位，进行战斗，更新数据行军队列数据，从事件队列取一个新的事件出来
    public static Object CMD_GAME_WORLD_EVENT_ARRIVE(RequestParam clientParam) throws Exception {
        CSGameWorldEventArriveRequest request = CSGameWorldEventArriveRequest.parseFrom(clientParam.getData());
        CSGameWorldEventArriveResponse.Builder response = CSGameWorldEventArriveResponse.newBuilder();
        long userId = clientParam.getUserId();

        int teamId = request.getTeamId();

        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldManager.checkWorldMoudleOpen(userInfo)) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }

        UserWorldTeam userWorldTeam = WorldManager.getUserWorldTeam(userId, teamId);
        if (userWorldTeam == null || userWorldTeam.getStatus() != WorldConstant.WORLD_TEAM_STATUS_1 || userWorldTeam.getLocationId() == 0) {
            return ErrorWord.INVALID_OPERATION;// 该队伍不是过去途中状态
        }

        long arriveTime = userWorldTeam.countArriveTime();// 到达的时间戳
        if (TimeUtils.getCurTime() + userWorldTeam.getReduceTime() < arriveTime) {
            return ErrorWord.ITEM_LACK;// 还没到达
        }

        int locationId = userWorldTeam.getLocationId();
        UserWorldEventLocation userWorldEventLocation = WorldManager.getUserWorldEventLocation(userId, locationId);


        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);

        WorldManager.handleTeamArrive(pbUserData, userInfo, userWorldInfo, userWorldTeam, userWorldEventLocation, false);// 行军到达事件地点时处理的事务

        userWorldEventLocation.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldEventLocation);

        userWorldTeam.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldTeam);

        return response;
    }


    // CMD_GAME_WORLD_EVENT_COMPLETE = 73504; // 行军队列回到基地，本次行军完成，生成战报，更新行军队列数据
    public static Object CMD_GAME_WORLD_EVENT_COMPLETE(RequestParam clientParam) throws Exception {
        CSGameWorldEventCompleteRequest request = CSGameWorldEventCompleteRequest.parseFrom(clientParam.getData());
        CSGameWorldEventCompleteResponse.Builder response = CSGameWorldEventCompleteResponse.newBuilder();
        long userId = clientParam.getUserId();

        int teamId = request.getTeamId();

        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldManager.checkWorldMoudleOpen(userInfo)) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }

        UserWorldTeam userWorldTeam = WorldManager.getUserWorldTeam(userId, teamId);
        if (userWorldTeam == null || userWorldTeam.getStatus() != WorldConstant.WORLD_TEAM_STATUS_2) {
            return ErrorWord.INVALID_OPERATION;// 该队伍不是返回途中
        }

        long curTime = TimeUtils.getCurTime();// 当前时间
        int diffTime = (int) (curTime - userWorldTeam.getUpdateTime()) + userWorldTeam.getReduceTime();// 离上次更新的间隔时间
        if (diffTime < userWorldTeam.getTimeLeft()) {
            return ErrorWord.ITEM_LACK;// 还没到达
        }

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        WorldManager.handleTeamComplete(pbUserData, userInfo, userWorldTeam);
        userWorldTeam.update();
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldTeam);

        return response;
    }

    // CMD_GAME_WORLD_ITEM_USE = 73505; // 使用道具，可以直接返回，或是加速行军
    public static Object CMD_GAME_WORLD_ITEM_USE(RequestParam clientParam) throws Exception {
        CSGameWorldItemUseRequest request = CSGameWorldItemUseRequest.parseFrom(clientParam.getData());
        CSGameWorldItemUseResponse.Builder response = CSGameWorldItemUseResponse.newBuilder();
        long userId = clientParam.getUserId();

        int teamId = request.getTeamId();
        int itemId = request.getItemId();
        int subNum = request.getNum();

        Item item = BagManager.getItem(itemId);
        if (item == null || (item.getEffectType() != BagConstant.ITEM_EFFECT_TYPE_43 && itemId != ItemId.DIAMOND)) {// 减少大世界的行军时间，减少时间数量配置在param2 单位分钟
            return ErrorWord.NOT_DATA;// 道具类型不对
        }

        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldManager.checkWorldMoudleOpen(userInfo)) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }

        long userItemNum = BagManager.getUserItemNum(userInfo, itemId);
        if (userItemNum < subNum) {
            return ErrorWord.ITEM_LACK;// 道具不足
        }

        Lock lock = null;
        try {
            lock = MainService.getVertLock(LockKey.getWorldTeam(userInfo.getId()));
            UserWorldTeam userWorldTeam = WorldManager.getUserWorldTeam(userId, teamId);
            if (userWorldTeam == null) {
                return ErrorWord.NOT_DATA;
            }

            long oldArriveTime = userWorldTeam.takeArriveTime(); // 旧的到达时间
            // 执行逻辑
            PBUserData.Builder pbUserData = response.getUserBuilder();
            UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
            userWorldTeam.refreshData(pbUserData, userInfo, userWorldInfo);
            if (userWorldTeam.getStatus() == WorldConstant.WORLD_TEAM_STATUS_1 || userWorldTeam.getStatus() == WorldConstant.WORLD_TEAM_STATUS_2) {
                long curTime = TimeUtils.getCurTime();
                int value = 0;// 一个道具减少的行军时间数量,单位秒
                if (itemId == ItemId.DIAMOND) {// 钻石
                    value = AllParam.WORLD_SPEED_UP_TIME_COST;//世界行军使用1个钻石可以加速5秒
                } else {
                    value = Integer.parseInt(item.getParam2());
                }

                double timeLeft = (double) userWorldTeam.getTimeLeft();
                int maxNum = (int) Math.ceil(timeLeft/value);// 到达终点需要消耗道具的最大数量


                if (subNum > maxNum) {
                    subNum = maxNum;
                }
                RewardManager.subReward(userInfo, itemId, subNum, pbUserData, LogType.WORLD_TEAM_ITEM_USE, teamId);// 扣除道具

                int subTime = subNum * value;// 减少的时长
                if (subTime < userWorldTeam.getTimeLeft()) {// 未完成当前单程
                    int newTimeLeft = userWorldTeam.getTimeLeft() - subTime;
                    userWorldTeam.putTimeLeft(newTimeLeft);
                    userWorldTeam.putUpdateTime(curTime);
                } else {// 完成当前行程，到达事件点，或是返回到基地
                    if (userWorldTeam.getStatus() == WorldConstant.WORLD_TEAM_STATUS_1) {// 出征途中，到达了位置，完成事件，需要刷新事件
                        UserWorldEventLocation userWorldEventLocation = WorldManager.getUserWorldEventLocation(userId, userWorldTeam.getLocationId());
                        WorldManager.handleTeamArrive(pbUserData, userInfo, userWorldInfo, userWorldTeam, userWorldEventLocation, true);// 行军到达事件地点时处理的事务

                        userWorldEventLocation.update();
                        ProtoDataUtils.updatePBUserData(pbUserData, userWorldEventLocation);
                    } else if (userWorldTeam.getStatus() == WorldConstant.WORLD_TEAM_STATUS_2) {// 返回途中，直接返回到基地
                        WorldManager.handleTeamComplete(pbUserData, userInfo, userWorldTeam);
                    }
                }
                boolean isResetWorldBossTimer = (userWorldTeam.getStatus() == WorldConstant.WORLD_TEAM_STATUS_1
                        && userWorldTeam.getLocationId() == WorldConstant.WORLD_EVENT_LOCATION_ID_BOSS);
                // 需要重新设置定时器
                if (isResetWorldBossTimer) {
                    // 已经起了定时器，只需要计算是否有滞后的往前面提
                    boolean isBattleTime = oldArriveTime > WorldBossManager.getBattleTime();
                    if (isBattleTime) { // 需要判断当前是否重新设置定时器
                        WorldBossManager.sendWorldBossTimer(userId,userWorldTeam);
                    }
                }
            }

            userWorldTeam.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userWorldTeam);
        } catch (Exception e) {
            return ErrorWord.PROTOCOL_PARSE_FAILED;
        } finally {// 释放锁
            MainService.releaseVertLock(lock);
        }

        return response;
    }


    // CMD_GAME_WORLD_RECALL_NOW = 73506; // 未到达坑位时使用道具立即撤退
    public static Object CMD_GAME_WORLD_RECALL_NOW(RequestParam clientParam) throws Exception {
        CSGameWorldRecallNowRequest request = CSGameWorldRecallNowRequest.parseFrom(clientParam.getData());
        CSGameWorldRecallNowResponse.Builder response = CSGameWorldRecallNowResponse.newBuilder();
        long userId = clientParam.getUserId();

        int teamId = request.getTeamId();

        PBUserData.Builder pbUserData = response.getUserBuilder();
        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldManager.checkWorldMoudleOpen(userInfo)) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }

        Lock lock = null;
        try {
            lock = MainService.getVertLock(LockKey.getWorldTeam(userInfo.getId()));
            UserWorldTeam userWorldTeam = WorldManager.getUserWorldTeam(userId, teamId);
            UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
            userWorldTeam.refreshData(pbUserData, userInfo, userWorldInfo);// 刷新队伍信息
            if (userWorldTeam == null || userWorldTeam.getStatus() != WorldConstant.WORLD_TEAM_STATUS_1) {
                return ErrorWord.WRONG_STATUS;// 该队伍不是出征途中
            }

            UserWorldEventLocation userWorldEventLocation = WorldManager.getUserWorldEventLocation(userId, userWorldTeam.getLocationId());
            if (userWorldEventLocation == null) {
                return ErrorWord.NOT_DATA;
            }

            int itemId = ItemId.TYPE_WORLD_RECALL_ITEM;
            long subNum = 1;
            long userItemNum = BagManager.getUserItemNum(userInfo, itemId);
            if (userItemNum < subNum) {
                itemId = ItemId.DIAMOND;
                subNum = AllParam.WORLD_RECALL_DIAMOND_NUM;
                userItemNum = BagManager.getUserItemNum(userInfo, itemId);// 钻石数量
            }
            if (userItemNum < subNum) {
                return ErrorWord.ITEM_LACK;// 道具不足
            }

            // 执行逻辑

            RewardManager.subReward(userInfo, itemId, subNum, pbUserData, LogType.WORLD_TEAM_RECALL, teamId);// 扣除道具

            UserWorldEventLocationTeam userWorldEventLocationTeam = WorldManager.getUserWorldEventLocationTeam(userId, userWorldTeam.getLocationId(), teamId);
            if (userWorldEventLocationTeam != null) {//  删除行军信息
                userWorldEventLocationTeam.delete();
                ProtoDataUtils.deletePBUserData(pbUserData, userWorldEventLocationTeam);
            }

            userWorldTeam.putStatus(WorldConstant.WORLD_TEAM_STATUS_2);// 更新状态
            int newTimeLeft = WorldManager.takeReturnTime(userWorldTeam.getOnewayTime() - userWorldTeam.getTimeLeft());// 返回需要花费的时间
            userWorldTeam.putTimeLeft(newTimeLeft);
            userWorldTeam.putUpdateTime(TimeUtils.getCurTime());
            userWorldTeam.putResult(WorldConstant.WORLD_EVENT_RESULT_999);// 撤退返回，不生成战报
            userWorldTeam.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userWorldTeam);
        } catch (InvalidProtocolBufferException e) {
            return ErrorWord.PROTOCOL_PARSE_FAILED;
        } finally {// 释放锁
            MainService.releaseVertLock(lock);
        }

        return response;
    }


    // CMD_GAME_WORLD_RECORD_LIST = 73507; // 读取战报列表 [3]每次打开请求增量下发
    public static Object CMD_GAME_WORLD_RECORD_LIST(RequestParam clientParam) throws Exception {
        CSGameWorldRecordListRequest request = CSGameWorldRecordListRequest.parseFrom(clientParam.getData());
        CSGameWorldRecordListResponse.Builder response = CSGameWorldRecordListResponse.newBuilder();
        long userId = clientParam.getUserId();

        long dbid = request.getDbid();

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        List<UserWorldRecord> list = WorldManager.getUserWorldRecordList(userId);
        for (UserWorldRecord userWorldRecord : list) {
            if (userWorldRecord.getId() > dbid) {
                ProtoDataUtils.updatePBUserData(pbUserData, userWorldRecord, true);
            }
        }

        return response;
    }

    // CMD_GAME_WORLD_RECORD_GET_REWARD = 73508; // 领取战报奖励
    public static Object CMD_GAME_WORLD_RECORD_GET_REWARD(RequestParam clientParam) throws Exception {
        CSGameWorldRecordGetRewardRequest request = CSGameWorldRecordGetRewardRequest.parseFrom(clientParam.getData());
        CSGameWorldRecordGetRewardResponse.Builder response = CSGameWorldRecordGetRewardResponse.newBuilder();
        long userId = clientParam.getUserId();

        long dbid = request.getDbid();

        List<UserWorldRecord> list = new ArrayList<>();
        if (dbid == 0) {
            list = WorldManager.getUserWorldRecordList(userId);
        } else {
            UserWorldRecord userWorldRecord = WorldManager.getUserWorldRecord(userId, dbid);
            if (userWorldRecord == null || userWorldRecord.isGet() || !userWorldRecord.hasReward()) {
                return ErrorWord.REPEATED_OPERATION;// 已经领取过了。或是无奖励
            }
            list.add(userWorldRecord);
        }

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        UserInfo userInfo = GameUser.getUserInfo(userId);
        long resourceNum = 0; // 資源數量
        for (UserWorldRecord userWorldRecord : list) {
            if (userWorldRecord.hasReward() && !userWorldRecord.isGet()) {// 有奖励且未领取过
                List<RewardItem> rewardItems = CommonUtils.takeReawrdItemFromStr(userWorldRecord.getReward());//
                WorldEvent worldEvent = WorldManager.getWorldEvent(userWorldRecord.getEventId());
                if (worldEvent != null){
                    if(worldEvent.isCollectionEvent()){
                        for (RewardItem rewardItem: rewardItems){
                            resourceNum +=rewardItem.getItemNum();
                        }
                    }
                }
                RewardManager.addReward(userInfo, rewardItems, pbUserData, LogType.WORLD_REWARD);
                userWorldRecord.putIsGetReward(1);// 标记为已经领取过
                userWorldRecord.update();
                ProtoDataUtils.updatePBUserData(pbUserData, userWorldRecord);
            }
        }
        if (resourceNum > 0){
            MainTaskManager.addTaskProgress(pbUserData,userInfo,MainTaskConstant.TASK_TYPE_260,resourceNum);  // 采集資源任務
        }
        return response;
    }


    // CMD_GAME_WORLD_RECORD_DEL_ALL = 73509; // 删除所有战报，已领取奖励，或是无奖励的战报
    public static Object CMD_GAME_WORLD_RECORD_DEL_ALL(RequestParam clientParam) throws Exception {
        CSGameWorldRecordDelAllRequest request = CSGameWorldRecordDelAllRequest.parseFrom(clientParam.getData());
        CSGameWorldRecordDelAllResponse.Builder response = CSGameWorldRecordDelAllResponse.newBuilder();
        long userId = clientParam.getUserId();

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        List<UserWorldRecord> list = WorldManager.getUserWorldRecordList(userId);
        for (UserWorldRecord userWorldRecord : list) {
            if (userWorldRecord.isGet() || !userWorldRecord.hasReward()) {// 已领取奖励，或是无奖励的战报都可以删除
                ProtoDataUtils.deletePBUserData(pbUserData, userWorldRecord);
                userWorldRecord.delete();
            }
        }

        return response;
    }

    // CMD_GAME_WORLD_REFRESH_EVENT = 73510; // 使用道具刷新事件
    public static Object CMD_GAME_WORLD_REFRESH_EVENT(RequestParam clientParam) throws Exception {
        CSGameWorldRefreshEventRequest request = CSGameWorldRefreshEventRequest.parseFrom(clientParam.getData());
        CSGameWorldRefreshEventResponse.Builder response = CSGameWorldRefreshEventResponse.newBuilder();
        long userId = clientParam.getUserId();

        int itemId = ItemId.TYPE_WORLD_REFRESH_EVENT;
        long subNum = 1;// 扣除数量
        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (BagManager.getUserItemNum(userInfo, itemId) < subNum) {
            return ErrorWord.ITEM_LACK;
        }

        UserBuild userBuild = BuildManager.getUserBuild(userId, BuildConstant.BUILD_ID_RADAR);
        WorldRadar worldRadar = WorldManager.getWorldRadar(userBuild.getLevel() + 1);// 按照下一级
        if (worldRadar == null) {
            worldRadar = WorldManager.getWorldRadar(userBuild.getLevel());
        }
        if (worldRadar == null) {
            return ErrorWord.NOT_DATA;
        }

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        RewardManager.subReward(userInfo, itemId, subNum, pbUserData, LogType.WORLD_REFRESH_EVENT);// 扣除道具
        UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
        WorldManager.refreshWorldTeam(pbUserData, userInfo, userWorldInfo);// 刷新结算行军队列，未到达则不做更新，已达到，则更新队伍，清除事件坑位里的数据，如果已返回基地，则生成战报，更新干员信息，伤兵信息
        WorldManager.refreshEvent(userId, userWorldInfo, worldRadar);// 刷新事件，放到事件队列里面
        List<UserWorldEventLocation> locationList = WorldManager.getUserWorldEventLocationList(userInfo.getId());
        WorldManager.updateAllEventLocation(userInfo, userWorldInfo, worldRadar, locationList, true);// 从事件队列里取事件更新到事件坑位
        for (UserWorldEventLocation userWorldEventLocation : locationList) {
            if (userWorldEventLocation.isCommonType()) {
                ProtoDataUtils.updatePBUserData(pbUserData, userWorldEventLocation);
            }
        }

        return response;
    }


    // CMD_GAME_WORLD_REFRESH_EVENT_EXTRA = 73511; // 使用道具刷新事件121001; 刷新额外的事件
    public static Object CMD_GAME_WORLD_REFRESH_EVENT_EXTRA(RequestParam clientParam) throws Exception {
        CSGameWorldRefreshEventExtraRequest request = CSGameWorldRefreshEventExtraRequest.parseFrom(clientParam.getData());
        CSGameWorldRefreshEventExtraResponse.Builder response = CSGameWorldRefreshEventExtraResponse.newBuilder();
        long userId = clientParam.getUserId();

        int itemId = ItemId.TYPE_WORLD_REFRESH_EVENT_EXTRA;
        long subNum = 1;// 扣除数量
        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (BagManager.getUserItemNum(userInfo, itemId) < subNum) {
            return ErrorWord.ITEM_LACK;
        }

        UserBuild userBuild = BuildManager.getUserBuild(userId, BuildConstant.BUILD_ID_RADAR);
        WorldRadar worldRadar = WorldManager.getWorldRadar(userBuild.getLevel());
        if (worldRadar == null) {
            return ErrorWord.NOT_DATA;
        }

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
        WorldManager.refreshWorldTeam(pbUserData, userInfo, userWorldInfo);// 刷新结算行军队列，未到达则不做更新，已达到，则更新队伍，清除事件坑位里的数据，如果已返回基地，则生成战报，更新干员信息，伤兵信息

        long refreshTime = WorldManager.getLastRefreshTime();// 每天的0点8点16点整点刷新，过去的最新一次的刷新时间
        UserWorldEventQueue userWorldEventQueue = WorldManager.creatEventEueqe(userId, worldRadar, refreshTime);
        UserWorldEventLocation userWorldEventLocationTarget = WorldManager.takeRefreshExtraEvent(userId);// 要刷新哪个坑位
        if (userWorldEventLocationTarget == null) {
            return ErrorWord.ALREADY_MAX;//事件已达上限，待行军队列完成事件后再使用
        }

        RewardManager.subReward(userInfo, itemId, subNum, pbUserData, LogType.WORLD_REFRESH_EVENT);// 扣除道具
        userWorldEventLocationTarget.cleanData();
        WorldManager.putEventToEventLocation(userWorldInfo, userWorldEventQueue, userWorldEventLocationTarget);// 把事件更新到事件坑位里，确定怪兽等级，随机怪兽战力, 删除事件队列里的数据
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldEventLocationTarget);
        userWorldEventQueue.delete();

        return response;
    }


    // CMD_GAME_WORLD_BOSS_INFO = 73513; // 世界boss伤害信息
    public static Object CMD_GAME_WORLD_BOSS_INFO(RequestParam clientParam) throws Exception {
        CsGameWorld.CSGameWorldBossInfoRequest request = CsGameWorld.CSGameWorldBossInfoRequest.parseFrom(clientParam.getData());
        CsGameWorld.CSGameWorldBossInfoResponse.Builder response = CsGameWorld.CSGameWorldBossInfoResponse.newBuilder();
        long userId = clientParam.getUserId();
        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (!WorldBossManager.isOpen(userInfo.getServerId())) {
            return ErrorWord.WRONG_STATUS;// 模块未解锁
        }
        Common.PBUserData.Builder pbUserData = response.getUserBuilder();
        UserWorldBossInfo userWorldBossInfo = WorldBossManager.getUserWorldBossInfo(userId);
        ProtoDataUtils.updatePBUserData(pbUserData, userWorldBossInfo, true);
        if (userWorldBossInfo.getIsQuit() == 0){
            UserUnion userUnion = UnionManager.getUserUnion(userId);
            if (userUnion.getUnionId() > 0){
                String dateKey2 = RankManager.getDateKey(RankConstant.SERVER_UNION_RANK_WORLD_BOSS);//今日的0点0分0秒
                long unionDamage = RankManager.getMyScore(RankConstant.SERVER_RANK_WORLD_BOSS, userInfo.getServerId(), userUnion.getUnionId(), dateKey2);
                response.setUnionDamage(unionDamage);
            }
        }
        String dateKey = RankManager.getDateKey(RankConstant.SERVER_RANK_WORLD_BOSS);//今日的0点0分0秒
        long damage = RankManager.getMyScore(RankConstant.SERVER_RANK_WORLD_BOSS, userInfo.getServerId(), userId, dateKey);
        response.setMyDamage(damage);
        return response;
    }


    // CMD_GAME_WORLD_ENERGY_BUY = 73520; // 购买体力
    public static Object CMD_GAME_WORLD_ENERGY_BUY(RequestParam clientParam) throws Exception {
        CSGameWorldEnergyBuyRequest request = CSGameWorldEnergyBuyRequest.parseFrom(clientParam.getData());
        CSGameWorldEnergyBuyResponse.Builder response = CSGameWorldEnergyBuyResponse.newBuilder();
        long userId = clientParam.getUserId();

        List<RewardItem> reward = CommonUtils.takeReawrdItemFromStr(AllParam.WORLD_ENERGY_GOODS);
        int[] price = AllParam.WORLD_ENERGY_PRICE;
        if (reward.size() == 0 || price.length == 0) {
            return ErrorWord.BAD_PARAM;// 配置错误
        }

        UserWorldInfo userWorldInfo = WorldManager.getUserWorldInfo(userId);
        int curNum = userWorldInfo.getEnergyBuyNum();
        if (curNum >= price.length) {
            return ErrorWord.ALREADY_MAX;// 限购次数上限
        }

        int itemId = ItemId.DIAMOND;// 扣除钻石
        int subNum = price[curNum];// 扣除数量
        UserInfo userInfo = GameUser.getUserInfo(userId);
        if (BagManager.getUserItemNum(userInfo, itemId) < subNum) {
            return ErrorWord.ITEM_LACK;// 钻石不足
        }

        // 执行逻辑
        PBUserData.Builder pbUserData = response.getUserBuilder();
        RewardManager.subReward(userInfo, itemId, subNum, pbUserData, LogType.WORLD_ENERGY_BUY, curNum);
        RewardManager.addReward(userInfo, reward, pbUserData, LogType.WORLD_ENERGY_BUY, curNum);

        userWorldInfo.addEnergyBuyNum(1);
        userWorldInfo.update();

        pbUserData.getWorldBuilder().getUserWorldInfoBuilder().setEnergyBuyNum(curNum + 1);
        ThinkingDataManager.pushUserWorldEnergyBuyEvent(userInfo, curNum + 1);// 数数上报数据

        return response;
    }

}
